package com.kexio.gen.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.kexio.gen.domain.entity.GenTable;
import com.kexio.gen.domain.entity.GenTableColumn;

/**
 * 配置校验和智能推荐服务
 *
 * @author 系统生成
 * @since 2024-12-19
 */
@Service
public class ConfigValidationService {

    /**
     * 校验表配置
     *
     * @param table 表配置
     * @param columns 字段配置列表
     * @return 校验结果
     */
    public ValidationResult validateConfig(GenTable table, List<GenTableColumn> columns) {
        ValidationResult result = new ValidationResult();
        
        // 校验基本信息
        validateBasicInfo(table, result);
        
        // 校验字段配置
        validateColumns(columns, result);
        
        // 校验权限配置
        validatePermissions(table, result);
        
        // 校验模板配置
        validateTemplate(table, result);
        
        return result;
    }
    
    /**
     * 智能推荐配置
     *
     * @param tableName 表名
     * @param columns 字段列表
     * @return 推荐配置
     */
    public ConfigRecommendation recommendConfig(String tableName, List<GenTableColumn> columns) {
        ConfigRecommendation recommendation = new ConfigRecommendation();
        
        // 推荐模块名
        String suggestedModule = inferModule(tableName);
        recommendation.setModuleName(suggestedModule);
        
        // 推荐实体名
        String suggestedEntity = toPascalCase(tableName);
        recommendation.setEntityName(suggestedEntity);
        
        // 推荐权限前缀
        String cleanName = cleanTableName(tableName);
        String suggestedPermission = suggestedModule + ":" + cleanName;
        recommendation.setPermissionPrefix(suggestedPermission);
        
        // 分析表结构推荐模板类型
        String suggestedTemplate = analyzeTableStructure(columns);
        recommendation.setTemplateType(suggestedTemplate);
        
        // 推荐UI组件
        for (GenTableColumn column : columns) {
            String component = inferUIComponent(column);
            recommendation.addUiRecommendation(column.getPropertyName(), component);
        }
        
        return recommendation;
    }
    
    private void validateBasicInfo(GenTable table, ValidationResult result) {
        if (isBlank(table.getTableName())) {
            result.addError("表名不能为空");
        }
        
        if (isBlank(table.getEntityName())) {
            result.addError("实体名不能为空");
        } else if (!table.getEntityName().matches("^[A-Z][a-zA-Z0-9]*$")) {
            result.addError("实体名必须符合驼峰命名规范，首字母大写");
        }
        
        if (isBlank(table.getModuleName())) {
            result.addError("模块名不能为空");
        } else if (!table.getModuleName().matches("^[a-z][a-z0-9]*$")) {
            result.addError("模块名必须为小写字母和数字组合");
        }
        
        if (!isBlank(table.getBasePackage())) {
            if (!table.getBasePackage().matches("^[a-z][a-z0-9]*(\\.[a-z][a-z0-9]*)*$")) {
                result.addError("基础包名格式不正确");
            }
        }
    }
    
    private void validateColumns(List<GenTableColumn> columns, ValidationResult result) {
        if (columns.isEmpty()) {
            result.addError("至少需要一个字段");
            return;
        }
        
        // 检查是否有主键
        boolean hasPrimaryKey = columns.stream()
            .anyMatch(c -> Boolean.TRUE.equals(c.getIsPk()));
        if (!hasPrimaryKey) {
            result.addWarning("建议设置主键字段");
        }
        
        // 检查字段命名规范
        Set<String> propertyNames = new HashSet<>();
        for (GenTableColumn column : columns) {
            if (isBlank(column.getPropertyName())) {
                result.addError("字段属性名不能为空: " + column.getColumnName());
            } else {
                if (!column.getPropertyName().matches("^[a-z][a-zA-Z0-9]*$")) {
                    result.addError("属性名必须符合驼峰命名规范: " + column.getPropertyName());
                }
                
                if (!propertyNames.add(column.getPropertyName())) {
                    result.addError("存在重复的属性名: " + column.getPropertyName());
                }
            }
            
            if (isBlank(column.getJavaType())) {
                result.addWarning("建议设置Java类型: " + column.getColumnName());
            }
        }
    }
    
    private void validatePermissions(GenTable table, ValidationResult result) {
        if (!isBlank(table.getPermissionPrefix())) {
            if (!table.getPermissionPrefix().matches("^[a-z]+:[a-z]+(:[a-z]+)*$")) {
                result.addError("权限前缀格式不正确，应为 module:entity 格式");
            }
        }
    }
    
    private void validateTemplate(GenTable table, ValidationResult result) {
        if ("multi".equals(table.getTemplateType())) {
            Object ext = table.getExt();
            if (ext == null) {
                result.addWarning("多表模板建议配置扩展信息");
            }
        }
    }
    
    private String inferModule(String tableName) {
        String name = tableName.toLowerCase();
        
        // 根据表名推断模块
        if (name.startsWith("sys_")) return "system";
        if (name.startsWith("user_") || name.contains("_user")) return "user";
        if (name.startsWith("order_") || name.contains("_order")) return "order";
        if (name.startsWith("product_") || name.contains("_product")) return "product";
        if (name.startsWith("pay_") || name.contains("_pay")) return "payment";
        if (name.startsWith("auth_") || name.contains("_auth")) return "auth";
        if (name.startsWith("gen_") || name.contains("_gen")) return "generator";
        
        return "business"; // 默认业务模块
    }
    
    private String analyzeTableStructure(List<GenTableColumn> columns) {
        Set<String> columnNames = columns.stream()
            .map(c -> c.getColumnName().toLowerCase())
            .collect(Collectors.toSet());
            
        // 检查是否有树形结构字段
        if (columnNames.contains("parent_id") || columnNames.contains("level") || columnNames.contains("path")) {
            return "tree";
        }
        
        // 检查是否有多租户字段
        if (columnNames.contains("tenant_id")) {
            return "tenant";
        }
        
        // 检查是否有审计字段
        if (columnNames.contains("created_at") || columnNames.contains("updated_at") ||
            columnNames.contains("created_by") || columnNames.contains("updated_by")) {
            return "audit";
        }
        
        return "basic";
    }
    
    private String inferUIComponent(GenTableColumn column) {
        if (column.getColumnName() == null || column.getJavaType() == null) {
            return "input";
        }
        
        String columnName = column.getColumnName().toLowerCase();
        String javaType = column.getJavaType();
        
        // 基于字段名推断
        if (columnName.contains("password")) return "password";
        if (columnName.contains("email")) return "email";
        if (columnName.contains("phone") || columnName.contains("mobile")) return "phone";
        if (columnName.contains("url") || columnName.contains("link")) return "url";
        if (columnName.contains("status") || columnName.contains("state")) return "select";
        if (columnName.contains("type") || columnName.contains("category")) return "select";
        if (columnName.endsWith("_at") || columnName.endsWith("_time")) return "datetime";
        if (columnName.endsWith("_date")) return "date";
        if (columnName.contains("content") || columnName.contains("desc") || columnName.contains("remark")) return "textarea";
        
        // 基于数据类型推断
        if ("Boolean".equals(javaType)) return "switch";
        if (javaType.matches("Integer|Long|BigDecimal|Double|Float")) return "number";
        if ("LocalDateTime".equals(javaType)) return "datetime";
        if ("LocalDate".equals(javaType)) return "date";
        if ("LocalTime".equals(javaType)) return "time";
        
        return "input"; // 默认输入框
    }
    
    private String toPascalCase(String tableName) {
        if (isBlank(tableName)) return "";
        
        return cleanTableName(tableName)
            .replace("_", " ")
            .replace("-", " ")
            .trim()
            .split(" ")
            .length == 0 ? "" : 
            String.join("", 
                java.util.Arrays.stream(cleanTableName(tableName)
                    .replace("_", " ")
                    .replace("-", " ")
                    .trim()
                    .split(" "))
                .filter(s -> !s.isEmpty())
                .map(word -> word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase())
                .toArray(String[]::new)
            );
    }
    
    private String cleanTableName(String tableName) {
        return tableName
            .replaceFirst("^(tb_|t_|sys_|gen_)", "") // 移除常见表前缀
            .toLowerCase();
    }
    
    private boolean isBlank(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    /**
     * 校验结果
     */
    public static class ValidationResult {
        private List<String> errors = new ArrayList<>();
        private List<String> warnings = new ArrayList<>();
        
        public boolean hasErrors() {
            return !errors.isEmpty();
        }
        
        public void addError(String error) {
            errors.add(error);
        }
        
        public void addWarning(String warning) {
            warnings.add(warning);
        }
        
        public List<String> getErrors() { return errors; }
        public List<String> getWarnings() { return warnings; }
    }
    
    /**
     * 配置推荐结果
     */
    public static class ConfigRecommendation {
        private String moduleName;
        private String entityName;
        private String permissionPrefix;
        private String templateType;
        private java.util.Map<String, String> uiRecommendations = new java.util.HashMap<>();
        
        public void addUiRecommendation(String propertyName, String component) {
            uiRecommendations.put(propertyName, component);
        }
        
        // Getters and setters
        public String getModuleName() { return moduleName; }
        public void setModuleName(String moduleName) { this.moduleName = moduleName; }
        public String getEntityName() { return entityName; }
        public void setEntityName(String entityName) { this.entityName = entityName; }
        public String getPermissionPrefix() { return permissionPrefix; }
        public void setPermissionPrefix(String permissionPrefix) { this.permissionPrefix = permissionPrefix; }
        public String getTemplateType() { return templateType; }
        public void setTemplateType(String templateType) { this.templateType = templateType; }
        public java.util.Map<String, String> getUiRecommendations() { return uiRecommendations; }
        public void setUiRecommendations(java.util.Map<String, String> uiRecommendations) { this.uiRecommendations = uiRecommendations; }
    }
}

